package https

import (
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
)

var client *http.Client
var cookie_jar *cookiejar.Jar

func init() {
	client = &http.Client{}

	var err error
	cookie_jar, err = cookiejar.New(nil)
	if err != nil {
		log.Printf("初始化cookiejar异常:" + err.Error())
	}
}

func Get(url string) (body string, err error) {
	return HttpHandle("GET", url, "", nil)
}

func Post(url string, content_Type string, content string) (body string, err error) {
	return HttpHandle("POST", url, content, map[string]string{
		"Content-Type": content_Type,
	})
}

func SetCookie(domain string, cookie string) (err error) {
	url, err := url.Parse(domain)
	if err != nil {
		return
	}

	cookies := splitCookieString(cookie)

	cookie_jar.SetCookies(url, cookies)
	return
}

func SetCookies(domain string, cookies []*http.Cookie) (err error) {
	url, err := url.Parse(domain)
	if err != nil {
		return
	}
	cookie_jar.SetCookies(url, cookies)
	return
}

func GetCookie(domain string) (cookie []*http.Cookie, err error) {
	url, err := url.Parse(domain)
	if err != nil {
		return
	}

	cookie = cookie_jar.Cookies(url)
	return
}

func HttpHandle(method string, url string, body string, headers map[string]string) (response_body string, err error) {
	var req *http.Request

	if body != "" {
		req, err = http.NewRequest(method, url, strings.NewReader(body))
	} else {
		req, err = http.NewRequest(method, url, nil)
	}

	cookies, err := GetCookie(url)
	if err != nil {
		return
	}

	if cookies != nil && len(cookies) > 0 {
		for _, item := range cookies {
			req.AddCookie(item)
		}
	}

	if headers != nil && len(headers) != 0 {
		for k, v := range headers {
			req.Header.Add(k, v)
		}
	}

	if err != nil {
		return
	}

	resp, err := client.Do(req)
	if err != nil {
		return
	}

	if resp_cookie := resp.Cookies(); resp_cookie != nil && len(resp_cookie) > 0 {
		SetCookies(url, resp_cookie)
	}

	defer resp.Body.Close()
	response_byte, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if resp.StatusCode/100 == 2 {
		response_body = string(response_byte)
	} else {
		err = errors.New(string(response_byte))
	}

	return
}

func splitCookieString(cookie_str string) (cookies []*http.Cookie) {
	cookie_items := strings.Split(cookie_str, ";")
	if cookie_items != nil && len(cookie_items) != 0 {
		for _, cookie_item_str := range cookie_items {
			index := strings.Index(cookie_item_str, "=")
			key := strings.TrimSpace(string([]rune(cookie_item_str)[:index]))
			value := strings.TrimSpace(string([]rune(cookie_item_str)[index+1:]))

			cookies = append(cookies, &http.Cookie{
				Name:  key,
				Value: value,
				Path:  "/",
			})
		}
	}
	return
}
